#ifndef _SMART_DEVICE_PROTOCOL_HEAD_H
#define _SMART_DEVICE_PROTOCOL_HEAD_H
#include <istream>
#include <vector>
using namespace std;

#define SMART_DEVICE_PROTOCOL_PACKET_FIX_LEN (9)

extern uint16_t calc_crc16(unsigned char *buf, int len);

class SmartDeviceProtocol
{
public:
	typedef struct
	{
		uint8_t head[2];
		uint8_t addr[4];
		uint8_t pid;
		uint8_t len[2];
		uint8_t data[1];
	} packet_t;

	enum
	{
		DOOR_LOCK_DEVICE_ADDR  = 0x00000001, //门锁
		ELECTRICAL_DEVICE_ADDR = 0x00000002, //电器
		SENSOR_DEVICE_ADDR     = 0x00000003, //传感器
		SNIFFING_DEVICE_ADDR   = 0xffffffff, //嗅探设备

	};

	enum
	{
		REQ_PACKET = 0x01,
		ACK_PACKET = 0x02,
	};

	enum
	{
		HANDLE_SUCCESS = 0x00,
		HANDLE_FIALURE = 0x01,
		PACKET_ERROR   = 0x02,
	};

	SmartDeviceProtocol();
	SmartDeviceProtocol(const vector<uint8_t> &packet);
	void addPakcetHead(uint16_t head = 0xffff);
	void addDeviceAddress(uint32_t addr);
	void addPacketID(uint8_t id);
	//添加数据内容
	void     addPacketData(uint8_t *data, uint16_t size);
	void     addCRC16(void);
	uint8_t *packetData(void);
	uint16_t packetLenth(void);

	//生成门锁的协议
	static SmartDeviceProtocol makeDoorLockProtocol(uint8_t deviceType,
	                                                uint8_t opCode,
	                                                uint8_t deviceNumber);

	//生成电器的协议
	static SmartDeviceProtocol makeElectricalProtocol(uint8_t deviceType,
	                                                  uint8_t opCode,
	                                                  uint8_t deviceNumber);

	//生成传感器的协议
	static SmartDeviceProtocol makeSensorcalProtocol(uint8_t deviceType,
	                                                 uint8_t opCode,
	                                                 uint8_t deviceNumber);

	//生成嗅探的协议
	static SmartDeviceProtocol makeSniffingProtocol(uint8_t deviceType,
	                                                uint8_t opCode,
	                                                uint8_t deviceNumber);

	//通过数据量实现协议
	static SmartDeviceProtocol makeProtocolFromPacket(const vector<uint8_t> &packet);

	uint16_t getPacketHead(void) const;
	uint32_t getPacketAddr(void) const;
	uint8_t  getPacketID(void) const;
	uint16_t getPacketDataLen(void) const;
	uint8_t *getPacketData(void) const;
	uint16_t getPacketCRC16(void) const;
	uint8_t  getPakcetErrorCode(void) const;
	void     showPacket(void) const;
	bool     isErrorPacket(void);

private:
	vector<uint8_t> packet;
};

#endif